# 支持向量存储

`VectorStoreRetrieverMemory`将记忆存储在向量存储中，并在每次调用时查询最“显著”的前K个文档。

与大多数其他记忆类不同，它不明确跟踪交互的顺序。

在这种情况下，“文档”是先前的对话片段。这可以用来引用AI在对话早期告诉的相关信息。

```python
from datetime import datetime
from langchain_openai import OpenAIEmbeddings
from langchain_openai import OpenAI
from langchain.memory import VectorStoreRetrieverMemory
from langchain.chains import ConversationChain
from langchain_core.prompts import PromptTemplate
```

### 初始化向量存储

根据您选择的存储方式，此步骤可能会有所不同。有关详细信息，请参阅相关向量存储的文档。

```python
import faiss

from langchain.docstore import InMemoryDocstore
from langchain_community.vectorstores import FAISS


embedding_size = 1536  # OpenAIEmbeddings的维度
index = faiss.IndexFlatL2(embedding_size)
embedding_fn = OpenAIEmbeddings().embed_query
vectorstore = FAISS(embedding_fn, index, InMemoryDocstore({}), {})
```

### 创建`VectorStoreRetrieverMemory`

从任何向量存储检索器实例化内存对象。

```python
# 在实际使用中，您可以将“k”设置为较高的值，这里我们使用k=1以显示向量查找仍然返回语义相关信息
retriever = vectorstore.as_retriever(search_kwargs=dict(k=1))
memory = VectorStoreRetrieverMemory(retriever=retriever)

# 当添加到代理器时，内存对象可以保存对话或使用的工具的相关信息
memory.save_context({"input": "我最喜欢的食物是比萨饼"}, {"output": "这是个好消息"})
memory.save_context({"input": "我最喜欢的运动是足球"}, {"output": "..."})
memory.save_context({"input": "我不喜欢凯尔特人队"}, {"output": "好的"})
```

```python
print(memory.load_memory_variables({"prompt": "我应该看什么运动?"})["history"])
```

---



```
    input: 我最喜欢的运动是足球
    output: ...
```

---



## 在链中使用
让我们通过一个示例来演示，再次设置`verbose=True`以便查看提示。

```python
llm = OpenAI(temperature=0)  # 可以是任何有效的LLM
_DEFAULT_TEMPLATE = """以下是AI与人类之间的友好对话。AI健谈，提供了很多上下文的具体细节。如果AI不知道问题的答案，它会诚实地说它不知道。

先前对话的相关片段：
{history}

（如果不相关，您不需要使用这些信息）

当前对话：
人类：{input}
AI:"""
PROMPT = PromptTemplate(
    input_variables=["history", "input"], template=_DEFAULT_TEMPLATE
)
conversation_with_summary = ConversationChain(
    llm=llm,
    prompt=PROMPT,
    memory=memory,
    verbose=True
)
conversation_with_summary.predict(input="你好，我叫Perry，怎么样？")
```

---



```


    > 进入新的ConversationChain链...
    格式化后的提示：
    以下是AI与人类之间的友好对话。AI健谈，提供了很多上下文的具体细节。如果AI不知道问题的答案，它会诚实地说它不知道。

    先前对话的相关片段：
    输入：我最喜欢的食物是比萨饼
    输出：这是个好消息

    （如果不相关，您不需要使用这些信息）

    当前对话：
    人类：你好，我叫Perry，怎么样？
    AI:

    > 完成链





    “嗨Perry，我很好。你呢？”
```

---




```python
# 这里展示了与篮球相关的内容
conversation_with_summary.predict(input="我最喜欢的运动是什么？")
```

---



```


    > 进入新的ConversationChain链...
    格式化后的提示：
    以下是AI与人类之间的友好对话。AI健谈，提供了很多上下文的具体细节。如果AI不知道问题的答案，它会诚实地说它不知道。

    先前对话的相关片段：
    输入：我最喜欢的运动是足球
    输出：...

    （如果不相关，您不需要使用这些信息）

    当前对话：
    人类：我最喜欢的运动是什么？
    AI:

    > 完成链





    '你之前告诉我你最喜欢的运动是足球。'
```

---




```python
# 即使语言模型是无状态的，由于获取了相关的记忆，它可以“推理”出时间的概念。
# 对记忆和数据进行时间戳是有用的，以便让代理程序确定时态相关性
conversation_with_summary.predict(input="我的最爱是什么食物")
```

---



```


    > 进入新的ConversationChain链...
    格式化后的提示：
    以下是AI与人类之间的友好对话。AI健谈，提供了很多上下文的具体细节。如果AI不知道问题的答案，它会诚实地说它不知道。

    先前对话的相关片段：
    输入：我最喜欢的食物是比萨饼
    输出：这是个好消息

    （如果不相关，您不需要使用这些信息）

    当前对话：
    人类：我的最爱是什么食物
    AI:

    > 完成链





    '你说过你最喜欢的食物是比萨饼。'
```

---




```python
# 对话中的记忆会被自动存储，
# 由于此查询最符合上述引言聊天，代理程序能够“记住”用户的名字。
conversation_with_summary.predict(input="我的名字是什么？")
```

---



```


    > 进入新的ConversationChain链...
    格式化后的提示：
    以下是AI与人类之间的友好对话。AI健谈，提供了很多上下文的具体细节。如果AI不知道问题的答案，它会诚实地说它不知道。

    先前对话的相关片段：
    输入：你好，我叫Perry，怎么样？
    响应：嗨Perry，我很好。你呢？

    （如果不相关，您不需要使用这些信息）

    当前对话：
    人类：我的名字是什么？
    AI:

    > 完成链





    '你的名字是Perry。'
```

---

